package com.ycsj.common.base;

import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;

import com.lzy.okgo.OkGo;
import com.lzy.okgo.interceptor.HttpLoggingInterceptor;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.constant.SpinnerStyle;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import com.ycsj.common.R;
import com.ycsj.common.http.HttpProxy;
import com.ycsj.common.http.OkGoProcessor;
import com.ycsj.common.map.LocationManager;
import com.ycsj.common.map.LocationResultEntity;
import com.ycsj.common.map.LocationResultListener;
import com.ycsj.common.toast.ToastUtils;
import com.ycsj.common.toast.style.ToastQQStyle;
import com.ycsj.common.utils.DeviceUtils;
import com.ycsj.common.utils.SPUtil;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.cookie.CookieJarImpl;
import com.zhy.http.okhttp.cookie.store.PersistentCookieStore;
import com.zhy.http.okhttp.https.HttpsUtils;
import com.zhy.http.okhttp.log.LoggerInterceptor;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.OkHttpClient;

/**
 * Created by Administrator on 2018/3/14 0014.
 */

public class BaseApplication extends Application {

    //定义全局的网络请求的返回状态
    public static String ERROR = "服务器异常";

    //定义全局的返回错误的提示语
    public static final String STATEERROE = "异常,错误码是:";

    //定义全局的Context对象
    public static Context context;
    //定义全局的Handler对象
    public static Handler handler;
    //定义主线程对象
    public static Thread mainThread;
    //定义主线程的线程ID
    public static int mainThreadId;

    //返回AppLicatinon单例的方法
    private static volatile BaseApplication application;

    /**
     * static 代码段可以防止内存泄露
     * 统一配置下拉刷新的加载更多的样式
     * 如果对于指定的Activity或者Fragment需要指定单独的下拉刷新样式时,可在xml文件中对应的配置
     * <com.scwang.smartrefresh.layout.SmartRefreshLayout
     *    app:srlEnablePreviewInEditMode="true"  //是否开启预览模式
     *    android:background="#444444"          //背景色
     *    app:srlAccentColor="@android:color/white"  //下拉刷新图标和显示文字的种颜色
     *    app:srlPrimaryColor="#444444"         //背景色
     *
     *      <com.scwang.smartrefresh.layout.header.ClassicsHeader
     *          android:layout_width="match_parent"
     *          android:layout_height="wrap_content" />
     *
     * </com.scwang.smartrefresh.layout.SmartRefreshLayout>
     */

    static {

        //全局设置下拉刷新样式 Header
        SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
            @Override
            public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                //开始设置全局的基本参数（这里设置的属性只跟下面的ClassicsHeader绑定，其他Header不会生效，能覆盖DefaultRefreshInitializer的属性和Xml设置的属性）
                layout.setEnableHeaderTranslationContent(true);
                //全局设置主题颜色,第一个参数为下拉刷新的整体背景色,第二个参数为下拉箭头和文字的颜色
                layout.setPrimaryColorsId(R.color.transparent, R.color.white);
                return new ClassicsHeader(context).setSpinnerStyle(SpinnerStyle.Translate);//指定为经典Header，默认是 贝塞尔雷达Header
            }
        });

    }


    public static BaseApplication getInstance() {
        if (application == null) {
            synchronized (BaseApplication.class) {
                if (application == null) {
                    application = new BaseApplication();
                }
            }
        }
        return application;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //初始化上下文等对象
        initConnmon();


        //初始化okHttpUtils
        initOKhttp();

        //初始化OkGo
        initOkGo();

        //初始化网络代理,方便统一切换项目的网络访问框架
        initHttpManager();

        //初始化异常处理类,上线后打开这个方法
//        initCrashHandler();

        //配置本地数据库的操作
//        setupDatabase();

        //初始化定位
        initLocation();

        //初始化吐司工具类
        initToast();

        // 获取系统相关的信息
        initSysInfo();

        // Android P（Android 9）出现Detected problems with API compatibility
        closeAndroidPDialog();

    }


    /**
     * 获取系统相关信息
     */
    private void initSysInfo() {

        //获取手机厂商
        String sysBrand = DeviceUtils.getDeviceBrand();

        //获取系统版本号
        String sysVersion = DeviceUtils.getSysVersion();

//        LogUtils.iTag("test", "手机厂商是:" + sysBrand + ",系统版本号是:" + sysVersion);
    }


    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);

        //解决65536的报错,分包处理
//        MultiDex.install(this);
    }

    /**
     * 初始化吐司工具类
     */
    private void initToast() {
        ToastUtils.init(this);
        //配置吐司的样式
        ToastUtils.initStyle(new ToastQQStyle());
    }


    /**
     * 设置本地数据库
     */
    private void setupDatabase() {
        //创建shop.db数据库
//        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "shop.db", null);
        //获取可写数据库
//        SQLiteDatabase db = helper.getWritableDatabase();
        //获取数据库对象
//        DaoMaster daoMaster = new DaoMaster(db);
        //获取Dao对象管理者
//        daoSession = daoMaster.newSession();

    }
//    public static DaoSession getDaoInstant() {
//        return daoSession;
//    }

    /**
     * 初始化OkHttpUtils
     */
    private void initOKhttp() {
        //配置支持Https请求
        //配置Https证书
        try {
            //支持指定证书认证的Https请求
//            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(new InputStream[
//                    ]{getAssets().open("https.cer")}, null, null);
            //支持所有的Https请求
            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
            CookieJarImpl cookieJar = new CookieJarImpl(new PersistentCookieStore(getApplicationContext()));
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(new LoggerInterceptor("TAG"))
                    .connectTimeout(15000L, TimeUnit.MILLISECONDS)
                    .readTimeout(15000L, TimeUnit.MILLISECONDS)
                    .cookieJar(cookieJar)
                    .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                    //其他配置
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            return true;
                        }
                    })
                    .build();
            OkHttpUtils.initClient(okHttpClient);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 初始化OkGo
     */
    private void initOkGo() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo");
        //log打印级别，决定了log显示的详细程度
        loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);

        //log颜色级别，决定了log在控制台显示的颜色
        loggingInterceptor.setColorLevel(Level.INFO);
        builder.addInterceptor(loggingInterceptor);

        //全局的读取超时时间
        builder.readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

        //全局的写入超时时间
        builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

        //全局的连接超时时间
        builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

        //方法一：信任所有证书,不安全有风险
        com.lzy.okgo.https.HttpsUtils.SSLParams sslParams1 = com.lzy.okgo.https.HttpsUtils.getSslSocketFactory();

        //方法二：自定义信任规则，校验服务端证书
        //HttpsUtils.SSLParams sslParams2 = HttpsUtils.getSslSocketFactory(new SafeTrustManager());
        //方法三：使用预埋证书，校验服务端证书（自签名证书）
        //HttpsUtils.SSLParams sslParams3 = HttpsUtils.getSslSocketFactory(getAssets().open("srca.cer"));
        //方法四：使用bks证书和密码管理客户端证书（双向认证），使用预埋证书，校验服务端证书（自签名证书）
        //HttpsUtils.SSLParams sslParams4 = HttpsUtils.getSslSocketFactory(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"));

        builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager);

        OkGo.getInstance().init(this).setOkHttpClient(builder.build());
    }


    /**
     * 初始化网络代理
     * 这里采用的OkGo加载工具
     */
    private void initHttpManager() {
        HttpProxy.init(new OkGoProcessor());
    }


    /**
     * 初始化异常处理
     */
    private void initCrashHandler() {
        CrashHandler.getInstance().init();
    }


    /**
     * 初始化定位,根据项目需求实现
     */
    private void initLocation() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //启动定位功能呢
                LocationManager.getInstance().start(context);
                LocationManager.getInstance().setLocationResultListener(new LocationResultListener() {
                    @Override
                    public void locationListener(LocationResultEntity entity) {
                        //将当前定位的地址值存入到Sp中, 这里取 区(district)+街道(street)+标志物(aoiName)
//                        SPUtil.put(context, SpKeys.PROVINCE, entity.province);
//                        SPUtil.put(context, SpKeys.CITY, entity.cityName.substring(0, entity.cityName.length() - 1));
//                        SPUtil.put(context, SpKeys.ADDRESS, entity.district + entity.road + entity.aoiName);
//                        SPUtil.put(context, SpKeys.POSTION, entity.aoiName);
//                        SPUtil.put(context, SpKeys.AREA, entity.district + entity.road);

                        //保存省市区
                        SPUtil.put(context, SpKeys.PROVINCE, entity.province);
                        SPUtil.put(context, SpKeys.CITY, entity.cityName);
                        SPUtil.put(context, SpKeys.AREA, entity.district);
                    }
                });
            }
        }).start();
    }


    /**
     * 初始化一些常用的对象
     */
    private void initConnmon() {
        context = getApplicationContext();
        handler = new Handler();
        mainThread = Thread.currentThread();
        mainThreadId = android.os.Process.myTid();
    }


    /**
     * 判断当前进程是不是UI进程的方法
     *
     * @param context
     * @return
     */
    public static boolean inMainProcess(Context context) {
        String packageName = context.getPackageName();
        String processName = getProcessName(context);
        return packageName.equals(processName);
    }


    /**
     * 获取当前进程名
     *
     * @param context
     * @return 进程名
     */
    public static String getProcessName(Context context) {
        String processName = null;

        // ActivityManager
        ActivityManager am = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE));

        while (true) {
            for (ActivityManager.RunningAppProcessInfo info : am.getRunningAppProcesses()) {
                if (info.pid == android.os.Process.myPid()) {
                    processName = info.processName;
                    break;
                }
            }

            // go home
            if (!TextUtils.isEmpty(processName)) {
                return processName;
            }

            // take a rest and again
            try {
                Thread.sleep(100L);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * Android P（Android 9）出现Detected problems with API compatibility
     */
    private void closeAndroidPDialog() {
        try {
            Class aClass = Class.forName("android.content.pm.PackageParser$Package");
            Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Class cls = Class.forName("android.app.ActivityThread");
            Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
            declaredMethod.setAccessible(true);
            Object activityThread = declaredMethod.invoke(null);
            Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
            mHiddenApiWarningShown.setAccessible(true);
            mHiddenApiWarningShown.setBoolean(activityThread, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
